package com.one.group.admin.service.impl;


import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
import cn.hutool.core.convert.Convert;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.tenant.TenantManager;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.one.group.admin.mapper.AdminMapper;
import com.one.group.admin.mapper.AdminRoleMapper;
import com.one.group.enums.ResultEnum;
import com.one.group.model.dto.AdminDto;
import com.one.group.model.dto.AdminQueryDto;
import com.one.group.model.dto.LoginDto;
import com.one.group.model.dto.UpdateAdminRoleDto;
import com.one.group.model.entity.Admin;
import com.one.group.model.entity.AdminRole;
import com.one.group.model.vo.AdminListVo;
import com.one.group.service.AdminService;
import com.one.group.service.MenuService;
import com.one.group.utils.ThrowUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.UUID;

/**
 * {@code @Create:}  2025-09-28  14 : 55
 * {@code @Author:} Cherry
 * {@code @ToUser:} 凡是发生,皆有利于我。
 * ------------------------------------
 * {@code @note:}
 */
@DubboService
@Service
@Slf4j
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

    @Autowired
    private AdminRoleMapper adminRoleMapper;

    @Autowired
    private MenuService menuService;

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public boolean insertAdmin(AdminDto adminDto) {

        //1.数据重复性校验
        ThrowUtil.throwIf(adminDto == null, ResultEnum.USER_INFO_NOT_EMPTY);
        //2.判断用户名，邮箱，电话号码是否重复
        checkAdmin(adminDto);
        //3.默认使用手机号码的后6位作为初始密码
        String password = adminDto.getPhone().substring(5);

        //4.生成盐
        String salt = UUID.randomUUID().toString();


        //5.密码加密
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        String md5Password = md5.digestHex(password + salt);

        //6.拷贝数据到entity
        Admin admin = new Admin();
        BeanUtils.copyProperties(adminDto, admin);


        //7.存储盐和加密后的密码
        admin.setPassword(md5Password);
        admin.setSalt(salt);

        //8.保存到数据库
        return this.save(admin);
    }

    @Override
    public String login(LoginDto loginDto) {

        //1.根据用户名查询用户信息
        QueryWrapper lambdaQueryWrapper = QueryWrapper.create().from(Admin.class);
        lambdaQueryWrapper.eq(Admin::getUsername, loginDto.getUsername());
        //配置忽略多租户
        TenantManager.ignoreTenantCondition();
        Admin admin = getMapper().selectOneByQuery(lambdaQueryWrapper);

        ThrowUtil.throwIf(admin == null, ResultEnum.USERNAME_OR_PASSWORD_ERROR);


        //2.获取盐
        String salt = admin.getSalt();

        //3.再次进行加密
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        String md5Password = md5.digestHex(loginDto.getPassword() + salt);


        //4.使用加密后的密码和服务器存储的加密密码进行对比，如果一致就ok
        ThrowUtil.throwIf(!admin.getPassword().equals(md5Password), ResultEnum.USERNAME_OR_PASSWORD_ERROR);

//        //5.生成jwt令牌
//        Map<String,Object> map=new HashMap<>();
//        map.put("id",admin.getId()+"");
//        map.put("username",admin.getUsername());
//        map.put("name",admin.getName());
//        map.put("phone",admin.getPhone());
//        map.put("imageUrl",admin.getImageUrl());
//
//        //查询用户对应的权限，存储到jwt中  后期TODO redis进行存储
//        List<String> permissionListTags = menuService.findPermsByUserId(admin.getId());
//        map.put("permissionListTags", JsonUtils.objectToJson(permissionListTags));
//
//        String token = TokenUtils.createToken(map);
        // 登录成功后存储 tenant_id 到 Redis

        StpUtil.login(admin.getId(), new SaLoginParameter()
                .setExtra("tenant_id", admin.getTenantId()
                ));
        redisTemplate.opsForValue().set("userId", admin.getId());
        return StpUtil.getTokenValue();
    }

    @Override
    public void updateAdminRole(UpdateAdminRoleDto updateAdminRoleDto) {

        //1.先删除管理员的角色
        QueryWrapper queryWrapper = QueryWrapper.create().from(AdminRole.class);
        queryWrapper.eq(AdminRole::getAdminId, updateAdminRoleDto.getAdminId());
        adminRoleMapper.deleteByQuery(queryWrapper);

        //2.获取角色id集合
        List<Long> roleIds = updateAdminRoleDto.getRoleIds();

        //3.判断权限id集合不为空
        if (!CollectionUtils.isEmpty(roleIds)) {

            log.debug("往中间表插入数据...");
            roleIds.forEach(roleId -> {
                AdminRole adminRole = new AdminRole();
                adminRole.setAdminId(updateAdminRoleDto.getAdminId());
                adminRole.setRoleId(roleId);
                adminRoleMapper.insert(adminRole);
            });

        }

    }

    @Override
    public List<AdminListVo> findAdminByQueryDto(AdminQueryDto adminQueryDto) {
        //获取租户id
        Long tenantId =Convert.toLong(StpUtil.getExtra("tenant_id"));
        return adminMapper.findAdminByQueryDto(adminQueryDto.getName(), tenantId);
    }


    private void checkAdmin(AdminDto adminDto) {

        //1.查询用户名是否重复
        QueryWrapper usernameLambdaQueryWrapper = QueryWrapper.create().from(Admin.class);
        usernameLambdaQueryWrapper.eq(Admin::getUsername, adminDto.getUsername());

//        if (getMapper().selectOneByQuery(usernameLambdaQueryWrapper)!=null){
//            throw new BusinessException(ResultEnum.USERNAME_EXITS);
//        }

        ThrowUtil.throwIf(getMapper().selectOneByQuery(usernameLambdaQueryWrapper) != null, ResultEnum.USERNAME_EXITS);

        //2.查询手机号码是否重复
        QueryWrapper phoneLambdaQueryWrapper = QueryWrapper.create().from(Admin.class);
        phoneLambdaQueryWrapper.eq(Admin::getPhone, adminDto.getPhone());

        ThrowUtil.throwIf(getMapper().selectOneByQuery(phoneLambdaQueryWrapper) != null, ResultEnum.PHONE_EXITS);

        //3.查询邮箱是否存在
        QueryWrapper emailLambdaQueryWrapper = QueryWrapper.create().from(Admin.class);
        emailLambdaQueryWrapper.eq(Admin::getEmail, adminDto.getEmail());

        ThrowUtil.throwIf(getMapper().selectOneByQuery(emailLambdaQueryWrapper) != null, ResultEnum.EMAIL_EXITS);


    }


}
